#ifndef AVALON_SERVERSOCKET_HPP
#define AVALON_SERVERSOCKET_HPP
#include "Avalon/IO/ServerConnection.hpp"
#include "Avalon/Network/TcpClientSocketChannel.hpp"

namespace boost {
namespace asio {
  class io_service;
}
namespace system {
  class error_code;
}
}

namespace Avalon {
namespace Network {

  /*! \class TcpServerSocket
   *  \brief Implements a server socket.
   *  \author Kamal Mansouri <kranar@hotmail.com>
   */
  class TcpServerSocket : public IO::ServerConnection {
    public:

      //! Constructs a TcpServerSocket.
      /*!
        \param address The IP address to bind to.
      */
      TcpServerSocket(const IpAddress& address);

      virtual ~TcpServerSocket();

      virtual void Start();

      virtual Threading::Async<IO::Channel*>::Ptr Accept();

      virtual bool IsConnected();

      virtual void Close();

      virtual boost::signals2::connection ConnectClosedSignal(
        const ClosedSignal::slot_type& slot);

      virtual boost::signals2::connection ConnectClosedSignal(
        const ClosedSignal::slot_type& slot, bool* isConnected);

    private:
      boost::recursive_mutex m_mutex;
      IpAddress m_address;
      bool m_isConnected;
      boost::asio::io_service& m_ioService;
      void* m_acceptor;
      Threading::AsyncOwner<IO::Channel*>::Ptr m_acceptResult;
      boost::condition_variable_any m_acceptCondition;
      ClosedSignal m_closedSignal;

      void HandleAccept(const boost::shared_ptr<Detail::SocketType>& socket,
        const boost::system::error_code& error);
  };
}
}

#endif // AVALON_SERVERSOCKET_HPP
